package com.zj.helloview;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.ViewPart;

import com.zj.helloview.model.Category;
import com.zj.helloview.model.ModelProvider;
import com.zj.helloview.model.Person;
import com.zj.helloview.model.TodoMockModel;
import com.zj.helloview.treeviewer.edit.FirstNameEditingSupport;
import com.zj.helloview.treeviewer.edit.GenderEditingSupport;
import com.zj.helloview.treeviewer.edit.LastNameEditingSupport;
import com.zj.helloview.treeviewer.edit.MarriedEditingSupport;
import com.zj.helloview.treeviewer.filter.PersonFilter;
import com.zj.helloview.treeviewer.provider.TodoContentProvider;
import com.zj.helloview.treeviewer.provider.TodoLabelProvider;
import com.zj.helloview.treeviewer.sorter.MyViewerComparator;
import com.zj.helloview.treeviewer.util.SearchUtil;

public class TableView extends ViewPart {
	public static final String ID = Messages.TableView_0;

	private TableViewer viewer;
	// We use icons
	private static final Image CHECKED = Activator.getImageDescriptor(Messages.TableView_1).createImage();
	private static final Image UNCHECKED = Activator.getImageDescriptor(Messages.TableView_2).createImage();

	private MyViewerComparator comparator;

	private PersonFilter filter;

	private Text searchText;
	private static Color colorYellow = Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);

	private Menu headerMenu;

	private ListViewer tviewer;

	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		GridLayout layout = new GridLayout(2, false);
		parent.setLayout(layout);
		Label searchLabel = new Label(parent, SWT.NONE);
		searchLabel.setText(Messages.TableView_3);
		searchText = new Text(parent, SWT.BORDER | SWT.SEARCH);
		searchText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));

		createViewer(parent);

		// Set the sorter for the table
		comparator = new MyViewerComparator();
		viewer.setComparator(comparator);

		// New to support the search
		filter = new PersonFilter();
		searchText.addKeyListener(new KeyAdapter() {
			public void keyReleased(KeyEvent ke) {
				filter.setSearchText(searchText.getText());
				viewer.refresh();
			}

		});

		viewer.addFilter(filter);

//		tviewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
//		tviewer.setContentProvider(new TodoContentProvider());
//		tviewer.setLabelProvider(new TodoLabelProvider());
		tviewer = new ListViewer(parent);
		tviewer.setContentProvider(ArrayContentProvider.getInstance());
		tviewer.setLabelProvider(new LabelProvider() {
			@Override
			public String getText(Object element) {
				Category p = (Category) element;
				return p.getName();
			};
		});
		// Expand the tree
//		tviewer.setAutoExpandLevel(2);
		// Provide the input to the ContentProvider
		tviewer.setInput(new TodoMockModel().getCategories());

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		tviewer.getControl().setLayoutData(gridData);
		getSite().setSelectionProvider(tviewer);
		//add double click listener
		tviewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				IHandlerService handlerService = (IHandlerService) getSite()
						.getService(IHandlerService.class);
				try {
					handlerService.executeCommand(
							"com.zj.helloview.openCategoryEditor", null);
				} catch (Exception ex) {
					System.out.println(ex);
				}
			}
		});
	}

	private void createViewer(Composite parent) {
		viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
		createColumns(parent, viewer);
		final Table table = viewer.getTable();
		table.setHeaderVisible(true);
		table.setLinesVisible(true);

		viewer.setContentProvider(new ArrayContentProvider());
		// Get the content for the viewer, setInput will call getElements in the
		// contentProvider
		viewer.setInput(ModelProvider.getInstance().getPersons());
		// Make the selection available to other views
		getSite().setSelectionProvider(viewer);
		// Set the sorter for the table

		// Layout the viewer
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 2;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		viewer.getControl().setLayoutData(gridData);
	}

	public TableViewer getViewer() {
		return viewer;
	}

	// // This will create the columns for the table
	// private void createColumns(final Composite parent, final TableViewer
	// viewer) {
	// String[] titles = { "First name", "Last name", "Gender", "Married" };
	// int[] bounds = { 100, 100, 100, 100 };
	//
	// // First column is for the first name
	// TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0);
	// col.setLabelProvider(new ColumnLabelProvider() {
	// @Override
	// public String getText(Object element) {
	// Person p = (Person) element;
	// return p.getFirstName();
	// }
	//
	// });
	//
	// // Second column is for the last name
	// col = createTableViewerColumn(titles[1], bounds[1], 1);
	// col.setLabelProvider(new ColumnLabelProvider() {
	// @Override
	// public String getText(Object element) {
	// Person p = (Person) element;
	// return p.getLastName();
	// }
	// });
	//
	// // Now the gender
	// col = createTableViewerColumn(titles[2], bounds[2], 2);
	// col.setLabelProvider(new ColumnLabelProvider() {
	// @Override
	// public String getText(Object element) {
	// Person p = (Person) element;
	// return p.getGender();
	// }
	// });
	//
	// // // Now the status married
	// col = createTableViewerColumn(titles[3], bounds[3], 3);
	// col.setLabelProvider(new ColumnLabelProvider() {
	// @Override
	// public String getText(Object element) {
	// return null;
	// }
	//
	// @Override
	// public Image getImage(Object element) {
	// if (((Person) element).isMarried()) {
	// return CHECKED;
	// } else {
	// return UNCHECKED;
	// }
	// }
	// });
	//
	// }

	// This will create the columns for the table
	private void createColumns(final Composite parent, final TableViewer viewer) {
		headerMenu = new Menu(parent.getShell(), SWT.POP_UP);

		String[] titles = { Messages.TableView_4, Messages.TableView_5, Messages.TableView_6, Messages.TableView_7 };
		int[] bounds = { 100, 100, 100, 100 };

		// First column is for the first name
		TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0], 0);
		col.setLabelProvider(new StyledCellLabelProvider() {
			@Override
			public void update(ViewerCell cell) {
				String search = searchText.getText();
				Person person = (Person) cell.getElement();
				String cellText = person.getFirstName();
				cell.setText(cellText);
				if (search != null && search.length() > 0) {
					int intRangesCorrectSize[] = SearchUtil.getSearchTermOccurrences(search, cellText);
					List<StyleRange> styleRange = new ArrayList<StyleRange>();
					for (int i = 0; i < intRangesCorrectSize.length; i++) {
						int start = intRangesCorrectSize[i];
						int length = intRangesCorrectSize[++i];
						StyleRange myStyledRange = new StyleRange(start, length, null, colorYellow);

						styleRange.add(myStyledRange);
					}
					cell.setStyleRanges(styleRange.toArray(new StyleRange[styleRange.size()]));
				} else {
					cell.setStyleRanges(null);
				}

				super.update(cell);

			}
		});
		col.setEditingSupport(new FirstNameEditingSupport(viewer));

		// Second column is for the last name
		col = createTableViewerColumn(titles[1], bounds[1], 1);
		col.setLabelProvider(new CellLabelProvider() {
			@Override
			public void update(ViewerCell cell) {
				cell.setText(((Person) cell.getElement()).getLastName());
			}
		});
		col.setEditingSupport(new LastNameEditingSupport(viewer));

		// Now the gender
		col = createTableViewerColumn(titles[2], bounds[2], 2);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				Person p = (Person) element;
				return p.getGender();
			}
		});
		col.setEditingSupport(new GenderEditingSupport(viewer));

		// // Now the status married
		col = createTableViewerColumn(titles[3], bounds[3], 3);
		col.setLabelProvider(new ColumnLabelProvider() {
			@Override
			public String getText(Object element) {
				return null;
			}

			@Override
			public Image getImage(Object element) {
				if (((Person) element).isMarried()) {
					return CHECKED;
				} else {
					return UNCHECKED;
				}
			}
		});
		col.setEditingSupport(new MarriedEditingSupport(viewer));

	}

	private void createMenuItem(Menu parent, final TableColumn column) {
		final MenuItem itemName = new MenuItem(parent, SWT.CHECK);
		itemName.setText(column.getText());
		itemName.setSelection(column.getResizable());
		itemName.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				if (itemName.getSelection()) {
					column.setWidth(150);
					column.setResizable(true);
				} else {
					column.setWidth(0);
					column.setResizable(false);
				}
			}
		});

	}

	private TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) {
		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		column.setImage(CHECKED);
		column.addSelectionListener(getSelectionAdapter(column, colNumber));

		// Create the menu item for this column
		createMenuItem(headerMenu, column);

		return viewerColumn;

	}

	private SelectionAdapter getSelectionAdapter(final TableColumn column, final int index) {
		SelectionAdapter selectionAdapter = new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {

				comparator.setColumn(index);
				int dir = comparator.getDirection();
				viewer.getTable().setSortDirection(dir);
				if (dir == SWT.UP) {
					column.setImage(CHECKED);
				} else {
					column.setImage(UNCHECKED);
				}
				viewer.refresh();
			}
		};
		return selectionAdapter;
	}

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}
}